package Common
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.events.TimerEvent;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.getTimer;
	import flash.utils.Timer;
	/**
	 * ...
	 * @author Yevgeniy Logachev
	 */
	public class Animation extends Bitmap
	{
		private var m_frames:Vector.<BitmapData> 		= null;
		private var m_currentFrameBitmapData:BitmapData = null;
		private var m_framesOffset:Vector.<Point> 		= null;
		private var m_currentFrame:int 					= 0;
		private var m_totalFrames:int 					= 0;
		private var m_frameRateKoef:int 				= 0;
		private var m_isPlay:Boolean 					= false;
		
		public var m_lastTimeUpdate:uint 				= getTimer();
		
		private var m_currentX:Number 					= 0;
		private var m_currentY:Number 					= 0;
		
		public function Animation(source:MovieClip, frameRate:int, posX:int = 0, posY:int = 0, isPlay:Boolean = true) 
		{
			m_frames = new Vector.<BitmapData>();
			m_framesOffset = new Vector.<Point>();
			m_frameRateKoef = 1000 / frameRate;
			m_totalFrames = source.totalFrames;
			m_currentFrame = 0;
			source.stop();
			m_isPlay = isPlay;
			
			var matrix:Matrix = new Matrix(1, 0, 0, 1);		
			var maxWidth:int = source.getRect(source).width;
			var maxHeight:int = source.getRect(source).height;
			for (var i:int = 0; i < m_totalFrames; ++i)
			{
				var rect:Rectangle = source.getRect(source);
				if (maxWidth < source.getRect(source).width) maxWidth = source.getRect(source).width;
				if (maxHeight < source.getRect(source).height) maxHeight = source.getRect(source).height;
				var bitmapData:BitmapData = new BitmapData(rect.width, rect.height, true, 0x00000000);
				matrix.tx = -rect.x;
				matrix.ty = -rect.y;
				bitmapData.draw(source, matrix);
				m_frames.push(bitmapData);
				m_framesOffset.push(new Point(rect.x, rect.y));
				
				source.nextFrame();
			}
			
			m_currentFrameBitmapData = new BitmapData(maxWidth, maxHeight, true, 0x00000000);
			m_currentFrameBitmapData.copyPixels(m_frames[m_currentFrame], 
												new Rectangle(0, 0, m_frames[m_currentFrame].width, m_frames[m_currentFrame].height),
												new Point(0, 0));
			super(m_currentFrameBitmapData, "auto", true);
			super.x = posX + m_framesOffset[m_currentFrame].x;
			super.y = posY + m_framesOffset[m_currentFrame].y;
		}
		
		public function update():void
		{
			if (m_isPlay  && getTimer() - m_lastTimeUpdate > m_frameRateKoef)
			{
				m_lastTimeUpdate = getTimer();
				
				updateAnimation();
			}
		}
		
		public function updateAnimation():void
		{
			m_currentFrameBitmapData.fillRect(new Rectangle(0, 0, m_currentFrameBitmapData.width, m_currentFrameBitmapData.height), 0x00000000);
			m_currentFrameBitmapData.copyPixels(m_frames[m_currentFrame], 
												new Rectangle(0, 0, m_frames[m_currentFrame].width, m_frames[m_currentFrame].height),
												new Point(0, 0));
			
			if (++m_currentFrame >= m_totalFrames)
			{
				m_currentFrame = 0;
			}
		}
		
		public function play():void
		{
			m_isPlay = true;
		}
		
		public function stop():void
		{
			m_isPlay = false;
		}
		
		public function gotoAndStop(frame:int):void
		{
			stop();
			
			if (frame < m_totalFrames)
			{
				m_currentFrame = frame;
				updateAnimation();
			}
		}
		
		public function gotoAndPlay(frame:int):void
		{
			stop();
			
			if (frame < m_totalFrames)
			{
				m_currentFrame = frame;
				updateAnimation();
			}
			
			play();
		}
		
		public function checkCollision(object:BitmapData):Boolean
		{
			return m_currentFrameBitmapData.hitTest(new Point(x, y), 255,
								object,	new Point(0, 0), 255);
		}
		
		public function getBitmapData():BitmapData
		{
			return m_currentFrameBitmapData;
		}
		
		override public function set x(value:Number):void
		{
			super.x = value + m_framesOffset[m_currentFrame].x;
		}
		
		override public function set y(value:Number):void
		{
			super.y = value + m_framesOffset[m_currentFrame].y;
		}
		
		public function get currentFrame():int
		{
			return m_currentFrame;
		}
		
		public function get totalFrames():int
		{
			return m_totalFrames;
		}
		
		public function nextFrame():void
		{
			gotoAndStop(m_currentFrame + 1);
		}
	}

}